import _3d from "../_3d.js"

const App = function (element, options) {
    this._3d = _3d
    this.renderer = null
    this.scene = null
    this.camera = null
    this.controls = null
    this.el = null
    this.init(element, options)
    this.renderOrder = 1
    this.single = {} // 单例对象
}

//基础属性与方法
App.prototype = {
    init(element, options) {
        options = options || {}
        this.el = element // 1
        const width = this.el.offsetWidth
        const height = this.el.offsetHeight
        const asp = width / height

        // scene
        this.scene = new _3d.Scene() // 2

        // camera
        this.camera = new _3d.PerspectiveCamera(45, asp, 1, 100000)
        this.camera.position.set(30, 30, 30) // 3
        this.camera.lookAt(0,0,0)

        // renderer
        this.renderer = new _3d.WebGLRenderer({ antialias: true, alpha: true }) // 4
        this.renderer.setPixelRatio(window.devicePixelRatio)
        this.renderer.setSize(width, height)
        this.el.appendChild( this.renderer.domElement)
        this.renderer.setClearColor(options.clearColor || '#000')

        // 辅助
        if (options.axes)  this.scene.add(new _3d.AxesHelper(10))// 坐标轴辅助红x 绿y 蓝z
        if (options.gridHelper)  this.scene.add(new _3d.GridHelper(100, 100))// 网格参考线

        this.updateTween = (options.updateTween !== false)

        //按序渲染
        this.renderer.sortObjects = options.sortObjects

        //默认 自动监听窗口resize
        options.autoResize !== false ? this.onresize() : ''
    },
    render(callback) {
        callback()
        this.frameId = requestAnimationFrame(() =>  {
            this.render(callback)
            if(this.updateTween) _3d.TWEEN.update()
            if(this.single.css2dRenderer) this.single.css2dRenderer.cssRenderer.render(this.scene, this.camera)
            if(this.single.css3dRenderer) this.single.css3dRenderer.cssRenderer.render(this.scene, this.camera)
        })
    },
    destroy () {
        cancelAnimationFrame(this.frameId) //销毁requestAnimationFrame
        this._3d.TWEEN.removeAll()
        this.scene.traverse(e => {
            if(e.material) {
                if(Array.isArray(e.material)) {
                    e.material.forEach(m => m.dispose())
                }else {
                    e.material.dispose()
                }
            }
            if(e.geometry) e.geometry.dispose()
        })
        this.scene.dispose()
        this.controls ? this.controls.dispose() : ''
        // this.renderer.forceContextLoss() //销毁context
        this.renderer = null
        this.scene = null
        this.camera = null
    },
    initOrbitControls(dom) {
        const controls = new _3d.OrbitControls(this.camera, dom || this.renderer.domElement)
        controls.enableDamping = true  // 使动画循环使用时阻尼或自转 意思是否有惯性
        // controls.dampingFactor = 0.25; // 动态阻尼系数 就是鼠标拖拽旋转灵敏度
        controls.enableZoom = true  // 是否可以缩放
        controls.autoRotate = true  // 开启自转
        controls.autoRotateSpeed = 0.3 //自传速度
        // controls.minDistance = 0   // 设置相机距离原点的最近距离
        // controls.maxDistance = 1000; // 设置相机距离原点的最远距离
        controls.enablePan = true   // 是否开启右键拖拽
        // controls.maxPolarAngle = Math.PI / 2.2// 禁止入地
        this.controls = controls
        return controls
    },
    onresize() { //默认会调用
        window.addEventListener('resize', () => this.resize(), false)
    },
    resize() {
        if(this.camera instanceof _3d.PerspectiveCamera) {
            this.camera.aspect = this.el.offsetWidth / this.el.offsetHeight
            this.renderer.setSize(this.el.offsetWidth, this.el.offsetHeight) // 重新获取
            this.camera.updateProjectionMatrix()
            this.renderer.render(this.scene, this.camera)
        }
        if(this.single.css2dRenderer) this.single.css2dRenderer.cssRenderer.setSize( this.el.offsetWidth, this.el.offsetHeight )
        if(this.single.css3dRenderer) this.single.css3dRenderer.cssRenderer.setSize( this.el.offsetWidth, this.el.offsetHeight )
    }
}

export default App